//------------------------------------------------------------------------------
// Fichiers d'ent�te utilis�s
//------------------------------------------------------------------------------
#include "AdaptativeThresholdOperator.hpp"
#include "Tools/Logger.hpp"
#include <math.h>

//------------------------------------------------------------------------------
// Définition de constantes
//------------------------------------------------------------------------------
#define DEFAULT_EPSILON 6
#define DEFAULT_WINDOW 16

#define WEIGHT_PARENT 3
#define WEIGHT_CHILD 2
namespace ImageAnalysis
{
	//----------------------------------------------------------------------
	// Constructeur
	//----------------------------------------------------------------------
	AdaptativeThresholdOperator::AdaptativeThresholdOperator( Gradiant* gradiant, BinaryImage* thresholdedImage, ThresholdFinder* finder ):
	currentGradiant(gradiant),
	currentThresholdedImage(thresholdedImage),
	thresholdFinder(finder),
	thresholdEpsilon(DEFAULT_EPSILON)
	{

	}

	//----------------------------------------------------------------------
	// Destructeur
	//----------------------------------------------------------------------
	AdaptativeThresholdOperator::~AdaptativeThresholdOperator( )
	{

	}

	//----------------------------------------------------------------------
	//
	//----------------------------------------------------------------------
	void AdaptativeThresholdOperator::Process( )
	{
		Histogram * histogram = currentGradiant->GetHistogram( 0 );

		Region localRegion( 0,0, currentGradiant->GetWidth(), currentGradiant->GetHeight() );		
		
		unsigned char* regionThreshold = thresholdFinder->GetOneThreshold( &localRegion, currentGradiant );


		RecursiveSubdividing(localRegion, regionThreshold[0]+WEIGHT_PARENT*DEFAULT_EPSILON+1  );

		delete regionThreshold; 
		delete histogram;
	}	

	//------------------------------------------------------------------------------
	//
	//------------------------------------------------------------------------------
	// pt2 . . pt3
	//   . . . .
	//   . . . .
	// pt0 . . pt1
	void AdaptativeThresholdOperator::RecursiveSubdividing( Region& region, unsigned char parentThreshold )
	{		
		// Calcule de l'indice du point de départ de la région et l'histogramme de la région		
		int pixelIndex = region.X + region.Y*currentGradiant->GetWidth();		
		
		unsigned char* regionThreshold = thresholdFinder->GetOneThreshold( &region, currentGradiant );
		unsigned int t = ( WEIGHT_CHILD*regionThreshold[0] + WEIGHT_PARENT*parentThreshold) / (WEIGHT_CHILD+WEIGHT_PARENT);
        	unsigned char currentThreshold =  t;
		delete[] regionThreshold;

		int t1 = currentThreshold;
		int t2 = parentThreshold;
		Tools::ILogger::Log("t1:%d,t2:%d\n",t1,t2 );
		
		// On teste si la différence de seuil est importante		
		if( (fabs(t1-t2) < thresholdEpsilon )  || !(region.Width>DEFAULT_WINDOW && region.Height>DEFAULT_WINDOW) )
		//if( !(region.Width>16 && region.Height>16) )
		{
			unsigned char thresholdValue;
			int index = region.X + region.Y*region.Width;						
			for( int j=region.Y; j< region.Y+region.Height; ++j )
			{
				for( int i=region.X; i< region.X+region.Width; ++i )
				{
					index = i + j*currentGradiant->GetWidth();
					thresholdValue = (currentGradiant->GetGradiantNorm( index ) >= currentThreshold)?BinaryImage::WHITE_VALUE: BinaryImage::BLACK_VALUE;
					currentThresholdedImage->SetPixel( index, &thresholdValue );
				}
			}
		}
		else 
		{
			//  ________
			// | 2 | 3 |
			// |___|___|
			// | 0 | 1 |
			// |___|___|
			//
			
			int subRegionWidth;
			int subRegionHeight;
			int regionMiddleX;
			int regionMiddleY;
			
			// Calcul des indices et des largeurs des rï¿½gions suivant si la largeur est paire ou non
			if( region.Width%2 == 0)
			{
				subRegionWidth  = region.Width/2;
				regionMiddleX	= region.X + subRegionWidth;
			}
			else
			{
				subRegionWidth = ((region.Width-1)/2)+1;
				regionMiddleX = region.X + subRegionWidth-1;
			}
	
			// Calcul des indices et des largeurs des rï¿½gions suivant si la hauteur est paire ou non
			if( region.Height%2 == 0 )
			{
				subRegionHeight = region.Height/2;
				regionMiddleY   = region.Y + subRegionHeight;
			}
			else
			{
				subRegionHeight = ((region.Height-1)/2)+1;
				regionMiddleY   = region.Y + subRegionHeight-1;
			}			

			// Region0
			Region region0(region.X, region.Y, subRegionWidth, subRegionHeight);
			RecursiveSubdividing( region0, currentThreshold );

			// Region1
			Region region1(regionMiddleX, region.Y, subRegionWidth, subRegionHeight);
			RecursiveSubdividing( region1, currentThreshold );

			// Region2
			Region region2(region.X, regionMiddleY, subRegionWidth, subRegionHeight);
			RecursiveSubdividing( region2, currentThreshold );

			// Region3
			Region region3(regionMiddleX, regionMiddleY, subRegionWidth, subRegionHeight);
			RecursiveSubdividing( region3, currentThreshold );
		}
	}
}

